package com.roc.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.RollbackException;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.roc.bean.TblMgmRiskBack;
import com.roc.bean.TblMgmRiskBackLog;
import com.roc.dao.IBaseDao;
import com.roc.dao.ISQLBaseDao;
import com.roc.newPage.IPageDao;
import com.roc.pojo.Operators;
import com.roc.pojo.WindControllSta;
import com.roc.service.MarginAndReturnService;
import com.roc.service.ServiceException;
import com.roc.util.Constance;
import com.roc.util.DateUtil;
import com.roc.util.constant.SysLogType;

@Service
public class MarginAndReturnServiceImpl implements MarginAndReturnService{
	
	private static Logger logger = Logger.getLogger(MarginAndReturnServiceImpl.class);
	
	@Autowired
	private ISQLBaseDao sqlBaseDao;
	
	@Autowired
	private IBaseDao baseDao;
	
	@Autowired
	private IPageDao pageDao;

	@Transactional(rollbackFor = { ServiceException.class })
	@Override
	public Map<String, Object> addMargin(Operators logingMerchant,
			TblMgmRiskBack risk) throws ServiceException {
		Map<String,Object> result = new HashMap<String, Object>();
		result.put("flag", false);
		if(risk==null || risk.getMchntCd()==null || "".equals(Constance.Null2EmptyTrim(risk.getMchntCd()))){
			result.put("msg", "退货保证金信息为空");
			return result;
		}
		
		List<Object> paramsList = new ArrayList<Object>();
		try {
			logger.info("操作员【"+logingMerchant.getAccountNo()+"】添加商户【"+risk.getMchntCd()+"】退货保证金开始");
			
			String mchtCd = Constance.Null2EmptyTrim(risk.getMchntCd());
			String termId = Constance.Null2EmptyTrim(risk.getTermId());
			String securityAmt = Constance.Null2EmptyTrim(risk.getSecurityAmt());
			
			if("".equals(securityAmt) || !isNumber(securityAmt) || new BigDecimal(securityAmt).doubleValue()<0){
				result.put("msg", "保证金金额填写不规范");
				return result;
			}
			
			if("".equals(termId)){
				termId = "*";
			}
			
			String selectRiskCount = "SELECT count(1) FROM apstfr.tbl_mgm_risk_back t where t.mchnt_cd=?";
			Object isRiskExist = sqlBaseDao.findObj(selectRiskCount, new Object[]{mchtCd} );
			int riskCount = Integer.parseInt(String.valueOf(isRiskExist));
			if(riskCount > 0){
				result.put("msg", "保证金记录已存在");
				return result;
			}
			
			String selectMchtSql = "select t.mcht_cd,t.bank_belong_cd from tbl_mcht_inf t where t.mcht_cd=?";
			
			Object[] mchtObj = (Object[]) sqlBaseDao.findObj(selectMchtSql, new Object[]{mchtCd});
			if(mchtObj==null){
				result.put("msg", "商户【"+mchtCd+"】不存在");
				return result;
			}
			
			String insIdCd = Constance.Null2EmptyTrim(mchtObj[1]);
			if("".equals(insIdCd)){
				result.put("msg", "商户【"+mchtCd+"】的机构号【"+insIdCd+"】不存在");
				return result;
			}
			
			BigDecimal securityAmtBD = new BigDecimal(securityAmt);
			paramsList.clear();
			paramsList.add(insIdCd);
			paramsList.add(mchtCd);
			paramsList.add(termId);
			paramsList.add(securityAmtBD.doubleValue());
			paramsList.add(securityAmtBD.multiply(new BigDecimal("0.5")).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue());
			paramsList.add(logingMerchant.getId());
			
			
			String insertRiskBackSql = "insert into apstfr.tbl_mgm_risk_back (INS_ID_CD, MCHNT_CD, TERM_ID, SECURITY_AMT, CURRENT_AMT, BACK_AMT, REMARK1, REMARK2, REMARK3, REMARK4, REMARK5, REC_UPD_TS, REC_CRT_TS, OPER_ID, REMARK) "
					+" values (?, ?, ?, ?, ?, 0, '', '', '', '', '', '', sysdate, ?, '') ";
			
			int insertRiskBackCount = sqlBaseDao.deleteBySql(insertRiskBackSql, paramsList);
			if(insertRiskBackCount != 1){
				throw new ServiceException("操作员【"+logingMerchant.getAccountNo()+"对商户【"+mchtCd+"】保证金添加失败");
			}
			
			logger.info("操作员【"+logingMerchant.getAccountNo()+"对商户【"+mchtCd+"】保证金表数据插入成功");
			
			//保存保证金操作流水
			paramsList.clear();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			SimpleDateFormat sdf1 = new SimpleDateFormat("HHmmss");
			Date now = new Date();
			paramsList.add(sdf.format(now));
			paramsList.add(sdf1.format(now));
			paramsList.add(insIdCd);
			paramsList.add(mchtCd);
			paramsList.add(termId);
			paramsList.add(securityAmtBD.doubleValue());
			paramsList.add(logingMerchant.getId());
			paramsList.add("操作员【"+logingMerchant.getAccountNo()+"】保存保证金【"+securityAmtBD.doubleValue()+"】元");
			
			String insertRiskBackLogSql = " insert into apstfr.TBL_TFR_mchnt_back_LOG (TRANS_DT, TRANS_TM, KEY_RSP, INS_ID_CD, MCHNT_CD, TERM_ID, SECURITY_AMT, PRE_AMT, TRAN_AMT, CURRENT_AMT, OPR_TYPE, REMARK1, REMARK2, REMARK3, REMARK4, REMARK5, REMARK6, OPERATOR, REMARK, STATUS) "
					+"values (?, ?, '', ?, ?, ?, ?, '', '', '', '01', '', '', '', '', '', '', ?, ?, '00')";
			
			int insertRiskBackLogCount = sqlBaseDao.deleteBySql(insertRiskBackLogSql, paramsList);
			if(insertRiskBackLogCount != 1){
				throw new ServiceException("操作员【"+logingMerchant.getAccountNo()+"对商户【"+mchtCd+"】保证金操作流水添加失败");
			}
			//保存保证金操作日志
			baseDao.addSyslog(SysLogType.INSERT_MARGIN_BACK.getCode(),
					SysLogType.INSERT_MARGIN_BACK.getName(),
					logingMerchant.getAccountNo(), 
					"操作员【"+logingMerchant.getAccountNo()+"】保存保证金【"+securityAmtBD.doubleValue()+"】元");
			
			result.put("flag", true);
			
		} catch (Exception e) {
			logger.error("操作员【"+logingMerchant.getAccountNo()+"】添加商户【"+risk.getMchntCd()+"】退货保证金异常",e);
			throw new ServiceException("操作员【"+logingMerchant.getAccountNo()+"】添加退货保证金异常");
		}
		
		logger.info("操作员【"+logingMerchant.getAccountNo()+"】添加退货保证金成功");
		return result;
	}
	
	@Transactional(rollbackFor={ServiceException.class})
	@Override
	public Map<String, Object> updateMargin(Operators logingMerchant,
			String mchtCd, String securityAmt) throws ServiceException {
		List<Object> paramsList = new ArrayList<Object>();
		Map<String,Object> result = new HashMap<String, Object>();
		result.put("flag", false);
		
		try {
			
			if("".equals(mchtCd)){
				result.put("msg", "商户号为空");
				return result;
			}
			
			if("".equals(securityAmt) || !isNumber(securityAmt) || new BigDecimal(securityAmt).doubleValue()<0){
				result.put("msg", "保证金金额填写不规范");
				return result;
			}
			
			String selectRiskCount = "SELECT t.mchnt_cd,t.security_amt,t.ins_id_cd,t.term_id FROM apstfr.tbl_mgm_risk_back t where t.mchnt_cd=?";
			Object[] isRiskExist = (Object[]) sqlBaseDao.findObj(selectRiskCount, new Object[]{mchtCd} );
			
			if(isRiskExist != null){
				logger.info("操作员【"+logingMerchant.getAccountNo()+"】修改商户【"+mchtCd+"】退货保证金开始");
				String oldSecAmt = Constance.Null2EmptyTrim(isRiskExist[1]);//原保证金额
				String insIdCd = Constance.Null2EmptyTrim(isRiskExist[2]);//机构号
				String termId = Constance.Null2EmptyTrim(isRiskExist[3]);//终端号
				
				logger.info("操作员【"+logingMerchant.getAccountNo()+"】将商户【"+mchtCd+"】原保证金额【"+oldSecAmt+"】改为【"+securityAmt+"】");
				String updateSql = "update apstfr.tbl_mgm_risk_back t set t.security_amt=?,t.oper_id=?,t.rec_upd_ts=sysdate,t.current_amt=?,t.back_amt=0 where t.mchnt_cd=? ";
				BigDecimal securityAmtBD = new BigDecimal(securityAmt);
				paramsList.add(securityAmtBD.doubleValue());
				paramsList.add(logingMerchant.getId());
				paramsList.add(securityAmtBD.multiply(new BigDecimal("0.5")).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue());
				paramsList.add(mchtCd);
				
				int updateCount = sqlBaseDao.deleteBySql(updateSql, paramsList);
				if(updateCount != 1){
					throw new ServiceException("商户【"+mchtCd+"】退货保证金修改异常");
				}
				
				logger.info("操作员【"+logingMerchant.getAccountNo()+"】将商户【"+mchtCd+"】原退货保证金【"+oldSecAmt+"】修改为【"+securityAmt+"】成功");
				
				//保存保证金操作流水
				paramsList.clear();
				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
				SimpleDateFormat sdf1 = new SimpleDateFormat("HHmmss");
				Date now = new Date();
				paramsList.add(sdf.format(now));
				paramsList.add(sdf1.format(now));
				paramsList.add(insIdCd);
				paramsList.add(mchtCd);
				paramsList.add(termId);
				paramsList.add(securityAmtBD.doubleValue());
				paramsList.add(logingMerchant.getId());
				paramsList.add("操作员【"+logingMerchant.getAccountNo()+"】将保证金【"+oldSecAmt+"】元修改为【"+securityAmtBD.doubleValue()+"】元");
				
				String insertRiskBackLogSql = " insert into apstfr.TBL_TFR_mchnt_back_LOG (TRANS_DT, TRANS_TM, KEY_RSP, INS_ID_CD, MCHNT_CD, TERM_ID, SECURITY_AMT, PRE_AMT, TRAN_AMT, CURRENT_AMT, OPR_TYPE, REMARK1, REMARK2, REMARK3, REMARK4, REMARK5, REMARK6, OPERATOR, REMARK, STATUS) "
						+"values (?, ?, '', ?, ?, ?, ?, '', '', '', '01', '', '', '', '', '', '', ?, ?, '00')";
				
				int insertRiskBackLogCount = sqlBaseDao.deleteBySql(insertRiskBackLogSql, paramsList);
				if(insertRiskBackLogCount != 1){
					throw new ServiceException("操作员【"+logingMerchant.getAccountNo()+"将商户【"+mchtCd+"】原退货保证金【"+oldSecAmt+"】修改为【"+securityAmt+"】时保证金操作流水添加失败");
				}
				
				logger.info("操作员【"+logingMerchant.getAccountNo()+"将商户【"+mchtCd+"】原退货保证金【"+oldSecAmt+"】修改为【"+securityAmt+"】时保证金操作流水添加成功");
				
				//保存保证金操作日志
				baseDao.addSyslog(SysLogType.UPDATE_MARGIN_BACK.getCode(),
						SysLogType.UPDATE_MARGIN_BACK.getName(),
						logingMerchant.getAccountNo(), 
						"操作员【"+logingMerchant.getAccountNo()+"】将商户【"+mchtCd+"】原退货保证金【"+oldSecAmt+"】修改为【"+securityAmt+"】元");
				result.put("msg", "操作成功");
				result.put("flag", true);
				
				
			}else{
				result.put("msg", "保证金记录不存在");
				return result;
			}
			
		} catch (Exception e) {
			logger.error("操作员【"+logingMerchant.getAccountNo()+"】修改商户【"+mchtCd+"】退货保证金异常",e);
			throw new ServiceException("操作员【"+logingMerchant.getAccountNo()+"】修改退货保证金异常");
		}
		
		logger.info("操作员【"+logingMerchant.getAccountNo()+"】修改商户【"+mchtCd+"】退货保证金成功");
		return result;
	}
	
	
	
	/**
	 * 正则表达式判断数字
	 * @param regextStr
	 * @param des
	 * @return
	 */
	public static boolean isNumber(String des){
		String regextStr = "[-|\\+]{0,1}\\d+[\\.]?\\d*|[-|\\+]{0,1}\\d*\\.\\d+";
		 Pattern pattern = Pattern.compile(regextStr);  
	     Matcher isNum = pattern.matcher(des);  
		return isNum.matches();
	}
	
	public static void main(String[] args) {
//		System.out.println(isNumber("-1..2"));
		//保留N位小数
		System.out.println(new BigDecimal("2.1").multiply(new BigDecimal("0.5")).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue());
	}

	@Transactional(propagation=Propagation.REQUIRED,readOnly=true)
	@Override
	public List<TblMgmRiskBackLog> queryMarginDetails(List<Object> params,int startRow, int maxRow)
			throws ServiceException {
		
		String sql = " select T.TRANS_DT,T.TRANS_TM,T.KEY_RSP,T.INS_ID_CD,T.MCHNT_CD,T.TERM_ID,T.SECURITY_AMT, "
				+" T.PRE_AMT,T.TRAN_AMT,T.CURRENT_AMT,T.OPR_TYPE,T.REMARK1,T.REMARK2,T.REMARK3,T.REMARK4, "
				+" T.REMARK5,T.REMARK6,T.OPERATOR,T.REMARK,T.STATUS,A.ACCOUNT_NO,m.name"
				+" from APSTFR.TBL_TFR_MCHNT_BACK_LOG T LEFT JOIN T_OPERATORS A ON T.OPERATOR=A.ID  "
				+" LEFT JOIN tbl_mcht_inf m on T.mchnt_cd=m.mcht_cd  WHERE "
				+" T.MCHNT_CD=?  order by t.trans_dt desc,t.trans_tm desc ";
		
		List<Object> searchRsList=new ArrayList<Object>();
		List<TblMgmRiskBackLog> riskList= new ArrayList<TblMgmRiskBackLog>();
		try {
			searchRsList = pageDao.findAllByParams(sql, params, startRow, maxRow);
			logger.info("查询到记录："+searchRsList.size()+"条");
			riskList = dealTheListSpecially(riskList,searchRsList);
		} catch (Exception e) {
			logger.error("退货保证金明细数据异常",e);
		}
		return riskList;
	}
	
	

	@Transactional(propagation=Propagation.REQUIRED,readOnly=true)
	@Override
	public int queryMarginDetailsCount(List<Object> params) throws ServiceException{
		String sql = " select count(1) "
				+" from APSTFR.TBL_TFR_MCHNT_BACK_LOG T LEFT JOIN T_OPERATORS A ON T.OPERATOR=A.ID LEFT JOIN tbl_mcht_inf m on T.mchnt_cd=m.mcht_cd WHERE "
				+" T.MCHNT_CD=? ";
		
		int rowCount = 0;
		try {
			rowCount = pageDao.countByParams(sql,params);
			logger.info("退货保证金明细数量查询sql结果："+rowCount);
		} catch (Exception e) {
			logger.error("退货保证金明细数量查询异常",e);
		}
		return rowCount;
	}
	
	private List<TblMgmRiskBackLog> dealTheListSpecially(
			List<TblMgmRiskBackLog> riskList, List<Object> searchRsList) {
		try {
			if(searchRsList != null && searchRsList.size()>0){
				Iterator it = searchRsList.iterator();
				while(it.hasNext()){
					Object[] obj = (Object[]) it.next();
					
					TblMgmRiskBackLog riskLog = new TblMgmRiskBackLog();
					riskLog.setTransDt(Constance.Null2EmptyTrim(obj[0]));
					riskLog.setTransMt(Constance.Null2EmptyTrim(obj[1]));
					riskLog.setKeyRsp(Constance.Null2EmptyTrim(obj[2]));
					riskLog.setInsIdCd(Constance.Null2EmptyTrim(obj[3]));
					riskLog.setMchtCd(Constance.Null2EmptyTrim(obj[4]));
					riskLog.setTermId(Constance.Null2EmptyTrim(obj[5]));
					riskLog.setSecurityAmt(Constance.Null2EmptyTrim(obj[6]));
					riskLog.setPreAmt(Constance.Null2EmptyTrim(obj[7]));
					riskLog.setTranAmt(Constance.Null2EmptyTrim(obj[8]));
					riskLog.setCurrentAmt(Constance.Null2EmptyTrim(obj[9]));
					riskLog.setOprType(Constance.Null2EmptyTrim(obj[10]));
					riskLog.setRemark1(Constance.Null2EmptyTrim(obj[11]));
					riskLog.setRemark2(Constance.Null2EmptyTrim(obj[12]));
					riskLog.setRemark3(Constance.Null2EmptyTrim(obj[13]));
					riskLog.setRemark4(Constance.Null2EmptyTrim(obj[14]));
					riskLog.setRemark5(Constance.Null2EmptyTrim(obj[15]));
					riskLog.setRemark6(Constance.Null2EmptyTrim(obj[16]));
					riskLog.setOperator(Constance.Null2EmptyTrim(obj[17]));
					riskLog.setRemark(Constance.Null2EmptyTrim(obj[18]));
					riskLog.setStatus(Constance.Null2EmptyTrim(obj[19]));
					riskLog.setAccountNo(Constance.Null2EmptyTrim(obj[20]));
					riskLog.setName(Constance.Null2EmptyTrim(obj[21]));
					riskList.add(riskLog);
				}
			}
		} catch (Exception e) {
			logger.error("解析退货保证金明细异常",e);
		}
		return riskList;
	}

}
